package com.orange.base.core.dao;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.springframework.jdbc.support.rowset.SqlRowSetMetaData;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.util.LinkedCaseInsensitiveMap;
import org.springframework.util.StringUtils;

import com.github.pagehelper.PageRowBounds;
import com.orange.base.core.bean.ColumnMetaData;
import com.orange.base.core.bean.TableIndexInfo;
import com.orange.base.core.bean.TableMetaData;
import com.orange.base.core.util.DbUtil;
import com.orange.base.core.util.MybatisUtil;

import cn.hutool.core.util.IdUtil;

/**
 * 操作数据库service,通过JdbcTemplate操作数据库
 * 
 * @author wlwang
 *
 */
@Service
public class DaoService {

	private static final Log LOGGER = LogFactory.getLog(DaoService.class);

	@Value("${spring.datasource.druid.dbType}")
	private String dbType;

	@Autowired
	private JdbcTemplate jdbcTemplate;

	@Autowired
	private PlatformTransactionManager transactionManager;

	public DaoService() {

	}

	public DaoService(JdbcTemplate jdbcTemplate, PlatformTransactionManager transactionManager) {
		this.jdbcTemplate = jdbcTemplate;
		this.transactionManager = transactionManager;
	}

	public PlatformTransactionManager getPlatformTransactionManager() {
		return this.transactionManager;
	}

	public JdbcTemplate getJdbcTemplate() throws Exception {
		return jdbcTemplate;
	}

	/**
	 * 生成插入SQL语句
	 * 
	 * @param tableName表名称
	 * @param data数据
	 * @return
	 * @throws Exception
	 */
	public static SqlWrapper getInsertSql(String tableName, Map<String, Object> data) throws Exception {
		StringBuilder sqlBuf = new StringBuilder();
		List<Object> params = new ArrayList<Object>();
		sqlBuf.append("INSERT INTO ").append(tableName).append("(");
		int index = 0;
		for (Iterator<String> iter = data.keySet().iterator(); iter.hasNext();) {
			String key = iter.next();
			Object value = data.get(key);
			if (index == 0) {
				sqlBuf.append(key);
			} else {
				sqlBuf.append(",").append(key);
			}
			params.add(value);
			index++;
		}
		sqlBuf.append(") VALUES (");
		sqlBuf.append(getSqlPlaceholder(params));
		sqlBuf.append(")");
		return new SqlWrapper(sqlBuf.toString(), params);
	}

	/**
	 * 生成更新SQL语句
	 * 
	 * @param tableName表名称
	 * @param keyNames主键
	 * @param data数据
	 * @return
	 * @throws Exception
	 */
	public static SqlWrapper getUpdateSql(String tableName, String[] keyNames, Map<String, Object> data)
			throws Exception {
		if (keyNames == null || keyNames.length < 1) {
			keyNames = new String[] { "WID" };
		}
		StringBuilder sqlBuf = new StringBuilder();
		List<Object> params = new ArrayList<Object>();
		sqlBuf.append("UPDATE ").append(tableName).append(" SET ");
		int index = 0;
		for (Iterator<String> iter = data.keySet().iterator(); iter.hasNext();) {
			boolean isContinue = false;
			String key = iter.next();
			for (int i = 0; i < keyNames.length; i++) {
				if (keyNames[i].equalsIgnoreCase(key)) {
					isContinue = true;
					break;
				}
			}
			if (isContinue) {
				continue;
			}
			Object value = data.get(key);
			if (index == 0) {
				sqlBuf.append(key).append(" = ?");
			} else {
				sqlBuf.append(",").append(key).append(" = ?");
			}
			params.add(value);
			index++;
		}
		// 添加数据过滤条件
		sqlBuf.append(" WHERE ");
		for (int i = 0, len = keyNames.length; i < len; i++) {
			if (i == 0) {
				sqlBuf.append(keyNames[i]).append(" = ? ");
			} else {
				sqlBuf.append(" AND ").append(keyNames[i]).append(" = ? ");
			}
			params.add(data.get(keyNames[i]));
		}
		return new SqlWrapper(sqlBuf.toString(), params);
	}

	/**
	 * 更新SQL语句
	 * 
	 * @param tableName表名称
	 * @param data数据
	 * @return
	 * @throws Exception
	 */
	public static SqlWrapper getUpdateSql(String tableName, Map<String, Object> data) throws Exception {
		return getUpdateSql(tableName, null, data);
	}

	/**
	 * 保存
	 * 
	 * @param tableName表名称
	 * @param data数据
	 * @return
	 * @throws Exception
	 */
	public String save(String tableName, Map<String, Object> data) throws Exception {
		if (data == null || data.isEmpty()) {
			return null;
		}
		SqlWrapper sw = getInsertSql(tableName, data);
		jdbcTemplate.update(sw.getSql(), sw.getParams().toArray());
		return (String) data.get("WID");
	}

	/**
	 * 更新
	 * 
	 * @param tableName表名称
	 * @param data数据
	 * @return
	 * @throws Exception
	 */
	public String update(String tableName, Map<String, Object> data) throws Exception {
		if (data == null || data.isEmpty()) {
			return null;
		}
		SqlWrapper sw = getUpdateSql(tableName, data);
		jdbcTemplate.update(sw.getSql(), sw.getParams().toArray());
		return (String) data.get("WID");
	}

	/**
	 * 根据WID判断保存还是更新
	 * 
	 * @param tableName
	 * @param data
	 * @return
	 * @throws Exception
	 */
	public String saveOrUpdate(String tableName, Map<String, Object> data) throws Exception {
		if (data == null || data.isEmpty()) {
			return null;
		}
		Object wid = data.get("WID");
		if (StringUtils.isEmpty(wid)) {
			data.put("WID", getNewWid());
			return save(tableName, data);
		} else {
			return update(tableName, data);
		}
	}

	/**
	 * 批量更新或者插入
	 * 
	 * @param tableName
	 * @param datas
	 * @throws Exception
	 */
	public void saveOrUpdate(String tableName, List<Map<String, Object>> datas) throws Exception {
		if (datas == null || datas.isEmpty()) {
			return;
		}
		List<Map<String, Object>> saveList = new ArrayList<Map<String, Object>>();
		List<Map<String, Object>> updateList = new ArrayList<Map<String, Object>>();
		for (Map<String, Object> data : datas) {
			Object wid = data.get("WID");
			if (StringUtils.isEmpty(wid)) {
				data.put("WID", getNewWid());
				saveList.add(data);
			} else {
				updateList.add(data);
			}
		}
		if (!saveList.isEmpty()) {
			save(tableName, saveList);
		}
		if (!updateList.isEmpty()) {
			update(tableName, updateList);
		}
	}

	/**
	 * 批量保存
	 * 
	 * @param tableName
	 * @param datas
	 * @throws Exception
	 */
	public void save(String tableName, List<Map<String, Object>> datas) throws Exception {
		if (datas == null || datas.isEmpty()) {
			return;
		}
		checkListElementEqual(datas);
		StringBuilder sb = new StringBuilder("INSERT INTO ").append(tableName).append(" ( ");
		Map<String, Object> data = datas.get(0);
		int index = 0;
		final List<String> keys = new ArrayList<String>();
		for (Iterator<Entry<String, Object>> iter = data.entrySet().iterator(); iter.hasNext();) {
			Entry<String, Object> entry = iter.next();
			if (index == 0) {
				sb.append(entry.getKey());
			} else {
				sb.append(",").append(entry.getKey());
			}
			keys.add(entry.getKey());
			index++;
		}
		sb.append(")").append(" VALUES (").append(getSqlPlaceholder(keys)).append(")");
		String sql = sb.toString();
		jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
			@Override
			public int getBatchSize() {
				// 这个方法设定更新记录数，通常List里面存放的都是我们要更新的，所以返回list.size();
				return datas.size();
			}

			@Override
			public void setValues(PreparedStatement ps, int i) throws SQLException {
				Map<String, Object> data = datas.get(i);
				int parameterIndex = 0;
				for (String key : keys) {
					Object object = data.get(key);
					if (object instanceof String) {
						ps.setString(++parameterIndex, (String) object);
					} else if (object instanceof Integer) {
						ps.setInt(++parameterIndex, (Integer) object);
					} else if (object instanceof Date) {
						Date date = (Date) object;
						ps.setDate(++parameterIndex, new java.sql.Date(date.getTime()));
					} else if (object instanceof byte[]) {
						ps.setBytes(++parameterIndex, (byte[]) object);
					} else {
						ps.setObject(++parameterIndex, object);
					}
				}
			}

		});
	}

	/**
	 * 批量更新
	 * 
	 * @param tableName
	 * @param datas
	 * @throws Exception
	 */
	public void update(String tableName, List<Map<String, Object>> datas) throws Exception {
		if (datas == null || datas.isEmpty()) {
			return;
		}
		checkListElementEqual(datas);
		StringBuilder sb = new StringBuilder("UPDATE ").append(tableName).append(" SET ");
		Map<String, Object> data = datas.get(0);
		int index = 0;
		final List<String> keys = new ArrayList<String>();
		for (Iterator<Entry<String, Object>> iter = data.entrySet().iterator(); iter.hasNext();) {
			Entry<String, Object> entry = iter.next();
			String key = entry.getKey();
			keys.add(key);
			if (index == 0) {
				sb.append(key).append(" = ?");
			} else {
				sb.append(",").append(key).append(" = ?");
			}
			index++;
		}
		sb.append(" WHERE WID = ?");
		String sql = sb.toString();
		jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
			@Override
			public int getBatchSize() {
				// 这个方法设定更新记录数，通常List里面存放的都是我们要更新的，所以返回list.size();
				return datas.size();
			}

			@Override
			public void setValues(PreparedStatement ps, int i) throws SQLException {
				Map<String, Object> data = datas.get(i);
				int parameterIndex = 0;
				for (String key : keys) {
					Object object = data.get(key);
					if (object instanceof String) {
						ps.setString(++parameterIndex, (String) object);
					} else if (object instanceof Integer) {
						ps.setInt(++parameterIndex, (Integer) object);
					} else if (object instanceof Date) {
						Date date = (Date) object;
						ps.setDate(++parameterIndex, new java.sql.Date(date.getTime()));
					} else if (object instanceof byte[]) {
						ps.setBytes(++parameterIndex, (byte[]) object);
					} else {
						ps.setObject(++parameterIndex, object);
					}
				}
				ps.setObject(++parameterIndex, data.get("WID"));
			}
		});
	}

	/**
	 * 根据WID删除数据
	 * 
	 * @param tableName
	 * @param wid
	 * @return
	 * @throws Exception
	 */
	public int deleteByWid(String tableName, String wid) throws Exception {
		String sql = "DELETE FROM " + tableName + " WHERE WID = ?";
		int result = jdbcTemplate.update(sql, wid);
		return result;
	}

	/**
	 * 根据过滤条件删除数据
	 * 
	 * @param tableName
	 * @param condition
	 * @param params
	 * @return
	 * @throws Exception
	 */
	public int delete(String tableName, String condition, Object[] params) throws Exception {
		String sql = "DELETE FROM " + tableName;
		if (!StringUtils.isEmpty(condition)) {
			sql += " WHERE " + condition;
		}
		int result = jdbcTemplate.update(sql, params);
		return result;
	}

	/**
	 * 执行SQL语句
	 * 
	 * @param sql
	 * @param params
	 * @return
	 * @throws Exception
	 */
	public int execute(String sql, Object[] params) throws Exception {
		int result = jdbcTemplate.update(sql, params);
		return result;
	}

	/**
	 * 查询数据
	 * 
	 * @param sql
	 * @param params
	 * @return
	 * @throws Exception
	 */
	public List<Map<String, Object>> query(String sql, Object[] params) throws Exception {
		if (params == null) {
			params = new Object[] {};
		}

		List<Map<String, Object>> datas = jdbcTemplate.query(sql, params, new OrangeColumnMapRowMapper());
		if (datas == null || datas.isEmpty()) {
			return new ArrayList<Map<String, Object>>();
		}

		return datas;
	}

	/**
	 * 传分页信息查询行数据
	 * 
	 * @param sql
	 * @param page
	 * @param sort
	 * @param params
	 * @return
	 * @throws Exception
	 */
	public List<Map<String, Object>> query(String sql, PageRowBounds page, String sort, Object[] params)
			throws Exception {
		if (params == null) {
			params = new Object[] {};
		}
		if (StringUtils.isEmpty(sort)) {
			sort = "WID";
		} else {
			String[] fields = sort.split(",");
			sort = "";
			for (int i = 0, len = fields.length; i < len; i++) {
				if (i > 0) {
					sort += ",";
				}
				String field = fields[i];
				if (field.startsWith("-")) {
					sort += field + " DESC ";
				} else {
					sort += field;
				}
			}
		}
		sql = sql + " ORDER BY " + sort;
		// 此处分页，使用Mybatis
		List<Map<String, Object>> datas = MybatisUtil.executeQuerySql(sql, params, page);
		if (datas == null || datas.isEmpty()) {
			return new ArrayList<Map<String, Object>>();
		}
		return datas;
	}

	/**
	 * 查询行数据
	 * 
	 * @param sql
	 * @param page
	 * @param params
	 * @return
	 * @throws Exception
	 */
	public List<Map<String, Object>> query(String sql, PageRowBounds page, Object[] params) throws Exception {
		List<Map<String, Object>> datas = query(sql, page, null, params);
		if (datas == null || datas.isEmpty()) {
			return new ArrayList<Map<String, Object>>();
		}
		return datas;
	}

	/**
	 * 查询一行数据
	 * 
	 * @param sql
	 * @param params
	 * @return
	 * @throws Exception
	 */
	public Map<String, Object> queryRow(String sql, Object[] params) throws Exception {
		List<Map<String, Object>> datas = query(sql, params);
		if (datas == null || datas.isEmpty()) {
			return new HashMap<String, Object>();
		}
		return datas.get(0);
	}

	/**
	 * 查询一行一列数据
	 * 
	 * @param sql
	 * @param params
	 * @return
	 * @throws Exception
	 */
	public Object queryOne(String sql, Object[] params) throws Exception {
		List<Map<String, Object>> datas = query(sql, params);
		if (datas == null || datas.isEmpty()) {
			return null;
		}
		return datas.get(0).values().iterator().next();
	}

	/**
	 * 查询第一个字段所有记录
	 * 
	 * @param sql
	 * @param params
	 * @return
	 * @throws Exception
	 */
	public List<Object> queryOnes(String sql, Object[] params) throws Exception {
		List<Map<String, Object>> datas = query(sql, params);
		if (datas == null || datas.isEmpty()) {
			return new ArrayList<Object>();
		}
		List<Object> list = new ArrayList<Object>();
		for (int i = 0, len = datas.size(); i < len; i++) {
			list.add(datas.get(i).values().iterator().next());
		}
		return list;
	}

	/**
	 * 结果转int
	 * 
	 * @param sql
	 * @param params
	 * @return
	 * @throws Exception
	 */
	public int queryParseInt(String sql, Object[] params) throws Exception {
		Object obj = queryOne(sql, params);
		if (obj == null) {
			return 0;
		}
		return Integer.parseInt(obj.toString());
	}

	/**
	 * 根据表查询数据
	 * 
	 * @param tablename
	 * @param condition
	 * @param params
	 * @return
	 * @throws Exception
	 */
	public List<Map<String, Object>> queryTable(String tablename, String condition, Object[] params) throws Exception {
		return queryTable(tablename, condition, params, null);
	}

	/**
	 * 查询数据，有排序
	 * 
	 * @param tablename
	 * @param condition
	 * @param params
	 * @param sort
	 * @return
	 * @throws Exception
	 */
	public List<Map<String, Object>> queryTable(String tablename, String condition, Object[] params, String sort)
			throws Exception {
		String sql = "SELECT * FROM " + tablename;
		if (!StringUtils.isEmpty(condition)) {
			sql += " WHERE " + condition;
		}
		if (StringUtils.isEmpty(sort)) {
			sql += " ORDER BY WID";
		} else {
			sql += " ORDER BY ";
			String[] fields = sort.split(",");
			for (String field : fields) {
				if (field.trim().startsWith("-")) {
					sql += field + " DESC ,";
				} else {
					sql += field + " ,";
				}
			}
			sql += "WID";
		}
		return query(sql, params);
	}

	/**
	 * 根据wid查询
	 * 
	 * @param tablename
	 * @param wid
	 * @return
	 * @throws Exception
	 */
	public Map<String, Object> queryTableByWid(String tablename, String wid) throws Exception {
		String sql = "SELECT * FROM " + tablename + " WHERE WID = ?";
		return queryRow(sql, new Object[] { wid });
	}

	/**
	 * 查询一条记录
	 * 
	 * @param tablename
	 * @param condition
	 * @param params
	 * @return
	 * @throws Exception
	 */
	public Map<String, Object> queryTableRow(String tablename, String condition, Object[] params) throws Exception {
		List<Map<String, Object>> datas = queryTable(tablename, condition, params);
		if (datas == null || datas.isEmpty()) {
			return new HashMap<String, Object>();
		}
		return datas.get(0);
	}

	/**
	 * 分页查询，没有排序
	 * 
	 * @param tablename表名称
	 * @param startIndex
	 * @param endIndex
	 * @param condition
	 * @param params
	 * @return
	 * @throws Exception
	 */
	public List<Map<String, Object>> queryTable(String tablename, PageRowBounds page, String condition, Object[] params)
			throws Exception {
		List<Map<String, Object>> datas = queryTable(tablename, page, null, condition, params);
		if (datas == null || datas.isEmpty()) {
			return new ArrayList<Map<String, Object>>();
		}
		return datas;
	}

	/**
	 * 分页查询数据,有排序
	 * 
	 * @param tablename
	 * @param startIndex
	 * @param endIndex
	 * @param ordery
	 * @param condition
	 * @param params
	 * @return
	 * @throws Exception
	 */
	public List<Map<String, Object>> queryTable(String tablename, PageRowBounds page, String ordery, String condition,
			Object[] params) throws Exception {
		String sql = "SELECT * FROM " + tablename;
		if (!StringUtils.isEmpty(condition)) {
			sql += " WHERE " + condition;
		}
		List<Map<String, Object>> datas = query(sql, page, ordery, params);
		if (datas == null || datas.isEmpty()) {
			return new ArrayList<Map<String, Object>>();
		}
		return datas;
	}

	/**
	 * 根据表，查询总记录书
	 * 
	 * @param tablename
	 * @param condition
	 * @param params
	 * @return
	 * @throws Exception
	 */
	public long queryTableCount(String tablename, String condition, Object[] params) throws Exception {
		String sql = "SELECT COUNT(1) FROM " + tablename;
		if (!StringUtils.isEmpty(condition)) {
			sql += " WHERE " + condition;
		}
		return queryParseInt(sql, params);
	}

	/**
	 * 生成新WID
	 * 
	 * @return
	 * @throws Exception
	 */
	public String getNewWid() throws Exception {
		return IdUtil.simpleUUID();
	}

//    @Cacheable(cacheNames = "cache", keyGenerator = "orangeCacheKeyGenerator")
//    public Map<String, Map<String, String>> getTableMeta(String tableName) throws Exception {
//        SqlRowSet rowSet = jdbcTemplate.queryForRowSet("SELECT * FROM " + tableName + " WHERE 1=0");
//        SqlRowSetMetaData metaData = rowSet.getMetaData();
//        int columnCount = metaData.getColumnCount();
//        Map<String, Map<String, String>> fieldsMap = new LinkedHashMap<String, Map<String, String>>(16);
//        for (int i = 1; i <= columnCount; i++) {
//            Map<String, String> fieldMap = new HashMap<String, String>(16);
//            String name = metaData.getColumnName(i);
//            // 列名称
//            fieldMap.put("ColumnName", name);
//            // 列类型
//            fieldMap.put("ColumnType", String.valueOf(metaData.getColumnType(i)));
//            // 列类型名称
//            fieldMap.put("ColumnTypeName", metaData.getColumnTypeName(i));
//            fieldMap.put("CatalogName", metaData.getCatalogName(i));
//            // 列对应的java类型
//            fieldMap.put("ColumnClassName", metaData.getColumnClassName(i));
//            // 列中文名称
//            fieldMap.put("ColumnLabel", metaData.getColumnLabel(i));
//            // 精度
//            fieldMap.put("Precision", String.valueOf(metaData.getPrecision(i)));
//            // 范围
//            fieldMap.put("Scale", String.valueOf(metaData.getScale(i)));
//            fieldMap.put("SchemaName", metaData.getSchemaName(i));
//            fieldMap.put("TableName", metaData.getTableName(i));
//            Map<String, String> unmodifiableMap = Collections.unmodifiableMap(fieldMap);
//            fieldsMap.put(name, unmodifiableMap);
//        }
//        Map<String, Map<String, String>> unmodifiableMap = Collections.unmodifiableMap(fieldsMap);
//        return unmodifiableMap;
//    }

	@Cacheable(cacheNames = "cache", keyGenerator = "orangeCacheKeyGenerator")
	public TableMetaData getTableMeta(String tableName) throws Exception {
		Connection conn = DbUtil.getDaoSevice().getJdbcTemplate().getDataSource().getConnection();
		try {
			DatabaseMetaData dbMetaData = conn.getMetaData();
			// 主键
			String primaryKey = getPrimaryKey(dbMetaData, tableName);
			// 索引
			List<TableIndexInfo> index = getIndexInfo(dbMetaData, tableName, primaryKey);
			// 列信息
			Map<String, ColumnMetaData> columnMap = getColumn(dbMetaData, tableName);

			TableMetaData tableMetaData = new TableMetaData(tableName, null, primaryKey, index, columnMap);
			return tableMetaData;
		} finally {
			conn.close();
		}
	}

	/**
	 * 获取表的主键名称
	 * 
	 * @param dbMetaData
	 * @param tableName
	 * @return
	 * @throws Exception
	 */
	private String getPrimaryKey(DatabaseMetaData dbMetaData, String tableName) throws Exception {
		String catalog = null;
		String schemaPattern = null;
		if ("oracle".equalsIgnoreCase(dbType)) {
			schemaPattern = dbMetaData.getUserName();
		}
		ResultSet resultSet = dbMetaData.getPrimaryKeys(catalog, schemaPattern, tableName);
		String primaryKey = null;
		while (resultSet.next()) {
			primaryKey = resultSet.getString("COLUMN_NAME");
		}
		if (StringUtils.isEmpty(primaryKey)) {
			primaryKey = "WID";
		}
		resultSet.close();
		return primaryKey;
	}

	/**
	 * 获取索引信息
	 * 
	 * @param dbMetaData
	 * @param tableName
	 * @return
	 * @throws Exception
	 */
	private List<TableIndexInfo> getIndexInfo(DatabaseMetaData dbMetaData, String tableName, String primaryKey)
			throws Exception {
		List<TableIndexInfo> index = new ArrayList<TableIndexInfo>();
		String catalog = null;
		String schemaPattern = null;
		if ("oracle".equalsIgnoreCase(dbType)) {
			schemaPattern = dbMetaData.getUserName();
		}
		ResultSet resultSet = dbMetaData.getIndexInfo(catalog, schemaPattern, tableName, false, false);
		while (resultSet.next()) {
			String indexName = resultSet.getString("INDEX_NAME");
			String columnName = resultSet.getString("COLUMN_NAME");
			boolean nonUnique = resultSet.getBoolean("NON_UNIQUE");
			if (primaryKey != null && primaryKey.equals(columnName)) {
				continue;
			}
			TableIndexInfo tableIndexInfo = new TableIndexInfo(indexName, columnName, nonUnique);
			index.add(tableIndexInfo);
		}
		resultSet.close();
		return index;
	}

	/**
	 * 获取表中列信息
	 * 
	 * @param dbMetaData
	 * @param tableName
	 * @return
	 * @throws Exception
	 */
	private Map<String, ColumnMetaData> getColumn(DatabaseMetaData dbMetaData, String tableName) throws Exception {
		Map<String, ColumnMetaData> columnMap = new LinkedHashMap<String, ColumnMetaData>();
		SqlRowSet rowSet = jdbcTemplate.queryForRowSet("SELECT * FROM " + tableName + " WHERE 1=0");
		SqlRowSetMetaData metaData = rowSet.getMetaData();
		int columnCount = metaData.getColumnCount();
		String catalog = null;
		String schemaPattern = null;
		if ("oracle".equalsIgnoreCase(dbType)) {
			schemaPattern = dbMetaData.getUserName();
		}
		ResultSet resultSet = dbMetaData.getColumns(catalog, schemaPattern, tableName, null);
		while (resultSet.next()) {
			String columnName = resultSet.getString("COLUMN_NAME");
			int columnSize = resultSet.getInt("COLUMN_SIZE");
			String remarks = resultSet.getString("REMARKS");
			int dataType = resultSet.getInt("DATA_TYPE");
			boolean nullable;
			if ("NO".equals(resultSet.getString("IS_NULLABLE"))) {
				nullable = false;
			} else {
				nullable = true;
			}
			String columnClassName = null;
			String type = null;
			for (int i = 1; i <= columnCount; i++) {
				String name = metaData.getColumnName(i);
				if (columnName.equals(name)) {
					columnClassName = metaData.getColumnClassName(i);
					if (columnClassName.equals("java.math.BigDecimal")) {
						columnClassName = "long";
					} else if (columnClassName.equals("java.lang.String")) {
						columnClassName = "String";
					}
					int index = columnClassName.lastIndexOf(".");
					if (index > 0) {
						type = columnClassName.substring(index + 1);
					} else {
						type = columnClassName;
					}
					type = type.toLowerCase();
					break;
				}
			}
			ColumnMetaData columnMetaData = new ColumnMetaData(columnName, columnSize, columnClassName, type, remarks,
					dataType, nullable);
			columnMap.put(columnName, columnMetaData);
		}
		resultSet.close();
		return columnMap;
	}

	/**
	 * 获取数据库类型
	 * 
	 * @return
	 * @throws Exception
	 */
	// TODO 多数据源的时候考虑如何处理
	@Cacheable(cacheNames = "cache", keyGenerator = "orangeCacheKeyGenerator")
	public String getDatabaseProductName() throws Exception {
		Connection conn = null;
		try {
			conn = jdbcTemplate.getDataSource().getConnection();
			DatabaseMetaData md = conn.getMetaData();
			return md.getDatabaseProductName();
		} finally {
			// 此次必须手动关闭连接，否则会出现连接池泄露
			conn.close();
		}
	}

	/**
	 * 校验集合元素是否相等
	 * 
	 * @param datas
	 * @throws Exception
	 */
	private void checkListElementEqual(List<Map<String, Object>> datas) throws Exception {
		int size = datas.size();
		if (size > 1) {
			Set<String> set0 = (datas.get(0)).keySet();
			for (int i = 1; i < size; i++) {
				if (!isEqualSet(set0, (datas.get(i)).keySet())) {
					LOGGER.error("set0:" + datas.get(0).toString());
					LOGGER.error("set" + i + ":" + datas.get(i).toString());
					throw new Exception("集合中的元素结构不一致,无法批量保存");
				}
			}
		}
	}

	/**
	 * 比较元素是否一致
	 * 
	 * @param set1
	 * @param set2
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private boolean isEqualSet(final Collection set1, final Collection set2) {
		if (set1 == set2) {
			return true;
		}
		if (set1 == null || set2 == null || set1.size() != set2.size()) {
			return false;
		}

		return set1.containsAll(set2);
	}

	/**
	 * 返回占位符
	 * 
	 * @param list
	 * @return
	 * @throws Exception
	 */
	private static String getSqlPlaceholder(List<?> list) throws Exception {
		StringBuilder sb = new StringBuilder();
		for (int i = 0, len = list.size(); i < len; i++) {
			if (i == 0) {
				sb.append("?");
			} else {
				sb.append(",?");
			}
		}
		return sb.toString();
	}

}

class OrangeColumnMapRowMapper implements RowMapper<Map<String, Object>> {

	@Override
	public Map<String, Object> mapRow(ResultSet rs, int rowNum) throws SQLException {
		ResultSetMetaData rsmd = rs.getMetaData();
		int columnCount = rsmd.getColumnCount();
		Map<String, Object> mapOfColValues = createColumnMap(columnCount);
		for (int i = 1; i <= columnCount; i++) {
			String key = getColumnKey(JdbcUtils.lookupColumnName(rsmd, i));
			Object obj = getColumnValue(rs, i);
			mapOfColValues.put(key.toUpperCase(), obj);
		}
		return mapOfColValues;
	}

	protected Map<String, Object> createColumnMap(int columnCount) {
		return new LinkedCaseInsensitiveMap<Object>(columnCount);
	}

	protected String getColumnKey(String columnName) {
		return columnName;
	}

	protected Object getColumnValue(ResultSet rs, int index) throws SQLException {
		return JdbcUtils.getResultSetValue(rs, index);
	}
}

class SqlWrapper {

	private String sql;

	private List<Object> params = new ArrayList<Object>();

	public SqlWrapper(String sql, List<Object> params) {
		this.sql = sql;
		this.params = params;
	}

	public String getSql() {
		return sql;
	}

	public void setSql(String sql) {
		this.sql = sql;
	}

	public List<Object> getParams() {
		return params;
	}

	public void setParams(List<Object> params) {
		this.params = params;
	}
}